////////////////////////////////////////////////////////////////////////////////
//
//	This file is part of Woozox, see <http://code.google.com/p/woozox/>.
//
//	Copyright 2008-2009 Florian David
//
//	Woozoo is free software: you can redistribute it and/or modify
//	it under the terms of the GNU Lesser General Public License as 
//	published by the Free Software Foundation, either version 3 of 
//	the License, or (at your option) any later version.
//
//	Woozoo is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//	GNU General Public License for more details.
//
//	You should have received a copy of the GNU Lesser General Public 
//	License along with Woozoo. If not, see <http://www.gnu.org/licenses/>.
//
////////////////////////////////////////////////////////////////////////////////
package org.woozoo.xhtml.core.base
{
	import flash.events.*;
	import flash.net.*;
	
	import org.woozoo.xhtml.core.base.selector.*;
	import org.woozoo.xhtml.core.manager.cache.CacheManager;
	import org.woozoo.xhtml.core.manager.element.ElementManager;
	import org.woozoo.xhtml.core.util.ElementArrayUtil;
	
	/**
	 * This is the class that represent an XHTML document
	 * */
	public class Document extends Element
	{
		private var __name : String;
		private var __url : String;
		
		private var __isLoaded : Boolean = false;
		private var __isReady : Boolean = false;
		private var __categories : Array = []; /* of Category */
		
		/**
		 * 
		 * */
		public function Document(name : String, url : String, source : * = null) {
			__name = name;
			__url = url;
			super(this, source);
		}
		
		/**
		 * 
		 * */
		public function get categories() : Array {
			return __categories;
		}
		public function set categories(value : Array) : void {
			__categories = value;
		}
		
		public function addCategory(category : Category) : void {
			if (__categories.indexOf(category) == -1) {
				__categories.push(category);
			}
		}
		
		/**
		 * 
		 * */
		public function load() : void {
			if (__isReady) {
				dispatchEvent(new Event(Event.COMPLETE));
				return;
			}
			
			var request : URLRequest = new URLRequest(url);
			var loader : URLLoader = new URLLoader();
			
			loader.addEventListener(Event.COMPLETE, __successHandler);
			loader.addEventListener(IOErrorEvent.IO_ERROR, __errorHandler);
			loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, __errorHandler);
			loader.load(request);
		}
		
		/**
		 * 
		 * */
		public function get metaTitle() : String {
			return getElementsByTagName('title')[0].innerHTML;
		}
		
		/**
		 * Proxy to getElementById()
		 * 
		 * @see #getElementById()
		 * @see org.woozoo.xhtml.core.API#$()
		 * */
		public function $(id : String) : Element {
			return getElementById(id);
		}
		
		/**
		 * @see org.woozoo.xhtml.core.API#querySelectorOnDocument()
		 * */
		public function querySelector(selectors : String) : Element {
			return querySelectorAll(selectors)[0];
		}
		
		/**
 		 * @see org.woozoo.xhtml.core.API#querySelectorOnAllDocument()
		 * */
		public function querySelectorAll(selectors : String) : Array {
			var cachedRes : Array = CacheManager.getInstance().getSelectorEntry(this, selectors);
			if (cachedRes)
				return cachedRes;
			
			var res : Array = [];
			var list : Array = selectors.split(',');
			var len : int = list.length;
			for (var i : int = 0; i < len; i++) {
				var selectorStr : String = list[i];
				var selector : Selector = new Selector(selectorStr, this);
				var lastRes : Array = selector.select();
				res = ElementArrayUtil.mergeUnique(res, lastRes);	
			}
			// if the len is equal to 1, the selector will do it by itself
			if (len > 1) {
				CacheManager.getInstance().addSelectorEntry(this, selectors, res);
			}
			return res;
		}
		
		/**
		 * @see org.woozoo.xhtml.core.API#querySelectorAll()
		 * */
		public function $$(selectors : String, selectAll : Boolean = true) : * {
			return selectAll ? querySelectorAll(selectors) : querySelector(selectors);
		}
		
		/**
		 * @see org.woozoo.xhtml.core.API#getElementById()
		 * */
		public function getElementById(id : String) : Element {
			var res : Element =  __getElementById(id, source.children());
			if (!res) {
				trace('Unable to find element with id '+id);
			}
			return res;
		}
		
		private function __getElementById(id : String, children : XMLList) : Element {
			var res : Element = null;
			var childrenLen : int = children.length();
			for (var  i : int = 0; i < childrenLen; i++) {
				var child : XML = children[i];
				var childrenOfChild : XMLList = child.children();
				var childrenOfChildLen : int = childrenOfChild.length();
				if (child.@id == id) {
					res =  ElementManager.getInstance().create(this, child);
					break;
				} else if (childrenOfChildLen > 0) {
					res = __getElementById(id, childrenOfChild);
					if (res) break;
				}
			}
			return res;
		}


		/**
		 * 
		 * */
		public function get url() : String {
			return __url;
		}

		/**
		 * 
		 * */
		public function get name() : String {
			return __name;
		}

		/**
		 * 
		 * */
		public function get isLoaded() : Boolean {
			return __isLoaded;
		}

		/**
		 * 
		 * */
		public function get isReady() : Boolean {
			return __isReady;
		}
		
		private function __successHandler(e : Event) : void {
			__isLoaded = true;
			
			var loader : URLLoader = e.currentTarget as URLLoader;
			source = loader.data;
			if (!isValid) {
				trace('Page '+name+' is not valid XHTML');
				return;
			}
			__isReady = true;
			dispatchEvent(e.clone());
		}
		
		private function __errorHandler(e : Event) : void {
			dispatchEvent(e.clone());
		}
	}
}